<?php


namespace App\Application\Middleware;


use App\Application\Services\Application\ApplicationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ApplicationApiHttpAuthMiddleware {
    /**
     * 中间件名称
     */
    const MIDDLEWARE_NAME = 'application.api.v1.http.auth';
    
    /**
     * 容器中app信息对象名称,通过 app()->make(\App\Http\Middleware\ApiV1HttpAuth::APP_CONTAINER_NAME); 获取
     */
    const APP_CONTAINER_NAME = 'applicationInfo';
    
    /**
     * Handle an incoming request.
     *
     * @param Request  $request
     * @param \Closure $next
     *
     * @return mixed
     * @throws \App\Exceptions\RepositoryException
     */
    public function handle(Request $request, \Closure $next) {
        $controller = null;
        
        if ($request->route()->controller) {
            $controller = $request->route()->getController();
            $actionName = $this->_getControllerActionName();//访问方法名获取 e.g, index 、 update
            
            //无需登录可访问控制器action
            if (
                property_exists($controller, 'noAuthActionList')
                &&
                is_array($controller->noAuthActionList) && !empty($controller->noAuthActionList)
                &&
                in_array($actionName, $controller->noAuthActionList)
            ) {
                return $next($request);
            }
        }
        //进行http验证
        if (!$this->_authCheck($request, $appEl)) {
            return (new JsonResponse(['code' => '401', 'message' => 'Authorization error'], 401))
                ->header('WWW-Authenticate', "Basic realm='please input auth info '");
        } else {
            //如果http验证通过，注册app信息容器
            app()->bind(self::APP_CONTAINER_NAME, function () use ($appEl) {
                return $appEl;
            });
        }
        
        return $next($request);
    }
    
    
    /**
     * http 基本验证信息是否正确
     *
     * @param Request $request
     *
     * @return bool
     * @throws \App\Exceptions\RepositoryException
     */
    private function _authCheck(Request $request, &$appEl) {
        //验证是否appId和密码正确
        return $request->header('Authorization')
               &&
               ($appId = $request->header('PHP_AUTH_USER'))
               &&
               ($appKey = $request->header('PHP_AUTH_PW'))
               &&
               ApplicationService::checkAppAuth($appId, $appKey, $appEl);
    }
    
    /**
     * 获取访问控制器的方法名称
     * @return bool|string
     */
    protected function _getControllerActionName() {
        $actionInfo  = request()->route()->getAction();
        $actionRoute = $actionInfo['uses'];//e.g App\Http\Controllers\Admin\IndexController@index
        
        return substr(strrchr($actionRoute, "@"), 1);//访问方法名获取 e.g, index 、 update
    }
}